#pragma once

#include "socket.hpp"
#include "calProtocol.hpp"
#include <string>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;

const size_t info_size = 128;

class tcp_cal_client
{
public:
    tcp_cal_client(const std::string &server_ip, const uint16_t port)
        : _server_ip(server_ip), _port(port)
    {
        // cout << _server_ip << ' ' << _port << endl;
    }
    ~tcp_cal_client() = default;
    void init()
    {
        if (!_sockfd.connect(_server_ip, _port))
        {
            perror("connect");
            exit(4);
        }
    }

    void start()
    {
        // 开始进行数据交互
        request rq;
        char inbuffer[info_size];
        while (true)
        {
            cout << "请输入左操作数：";
            cin >> rq._l;
            cout << "输入右操作数: ";
            cin >> rq._r;
            cout << "请输入操作符： ";
            cin >> rq._op;
            std::string rq_str = rq.seraliaze();
            std::string mesg = encode(rq_str);
            write(_sockfd.fd(), mesg.c_str(), mesg.size());
            response re;
            std::string read_mesg;
            while (true)
            {
                // cout << "read....\n";
                ssize_t n = read(_sockfd.fd(), inbuffer, info_size);
                // cout << "read done ...\n";
                if (n <= 0)
                {
                    perror("read");
                    exit(5);
                }
                inbuffer[n] = '\0';
                read_mesg += inbuffer;
                // cout << read_mesg << endl;
                if (get_response(read_mesg, &re))
                    break;
            }
            cout << "=================================\n";
            cout << "数据处理情况：" << re._exit_code << endl;
            cout << "计算结果：" << re._result << endl;
            cout << "=================================\n\n";
        }
    }

private:
    bool get_response(std::string &mesg, response *re)
    {
        std::string content;
        if (!decode(mesg, &content))
            return false;
        return (*re).deseraliaze(content);
    }

private:
    std::string _server_ip;
    uint16_t _port;
    tcp_socket _sockfd;
};